package cn.edu.tju.elm.service.impl;

import cn.edu.tju.core.model.User;
import cn.edu.tju.elm.dto.ReviewDto;
import cn.edu.tju.elm.model.Business;
import cn.edu.tju.elm.model.Food;
import cn.edu.tju.elm.model.Order;
import cn.edu.tju.elm.model.Review;
import cn.edu.tju.elm.repository.BusinessRepository;
import cn.edu.tju.elm.repository.FoodRepository;
import cn.edu.tju.elm.repository.OrderRepository;
import cn.edu.tju.elm.repository.ReviewRepository;
import cn.edu.tju.elm.service.ReviewService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.server.ResponseStatusException;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class ReviewServiceImpl implements ReviewService {

    @Autowired
    private ReviewRepository reviewRepository;
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private BusinessRepository businessRepository;
    
    @Autowired
    private FoodRepository foodRepository;
    
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    @Transactional
    public Review createReview(ReviewDto reviewDto, User currentUser) {
        // 1. 验证订单存在且属于当前用户
        Order order = orderRepository.findById(reviewDto.getOrderId())
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "订单不存在"));
                
        // 确保订单属于当前用户
        if (!order.getCustomer().getId().equals(currentUser.getId())) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "无权评价此订单");
        }
        
        // 2. 检查是否已评价过
        Optional<Review> existingReview = reviewRepository.findByOrderId(order.getId());
        if (existingReview.isPresent()) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "订单已评价，不能重复评价");
        }
        
        // 3. 验证商家存在
        Business business = businessRepository.findById(reviewDto.getBusinessId())
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "商家不存在"));
        
        // 4. 如果有指定商品ID，验证商品存在
        Food food = null;
        if (reviewDto.getFoodId() != null) {
            food = foodRepository.findById(reviewDto.getFoodId())
                    .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "商品不存在"));
            
            // 确保商品属于该商家
            if (!food.getBusiness().getId().equals(business.getId())) {
                throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "商品不属于该商家");
            }
        }
        
        // 5. 评分必须在1-5之间
        if (reviewDto.getRating() == null || reviewDto.getRating() < 1 || reviewDto.getRating() > 5) {
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "评分必须在1-5之间");
        }
        
        // 6. 创建新评价
        Review review = new Review();
        review.setUser(currentUser);
        review.setOrder(order);
        review.setBusiness(business);
        review.setFood(food); // 可能为null，表示对整个订单评价
        review.setRating(reviewDto.getRating());
        review.setContent(reviewDto.getContent());
        review.setImages(reviewDto.getImages());
        review.setIsAnonymous(reviewDto.getIsAnonymous() != null && reviewDto.getIsAnonymous());
        
        // 设置审计字段
        review.setCreator(currentUser.getId());
        review.setUpdater(currentUser.getId());
        LocalDateTime now = LocalDateTime.now();
        review.setCreateTime(now);
        review.setUpdateTime(now);
        review.setDeleted(false);
        
        // 7. 保存评价
        return reviewRepository.save(review);
    }

    @Override
    public ReviewDto getReviewByOrderId(Long orderId) {
        Optional<Review> reviewOpt = reviewRepository.findByOrderId(orderId);
        return reviewOpt.map(this::convertToDto).orElse(null);
    }

    @Override
    public List<ReviewDto> getReviewsByUserId(Long userId) {
        return reviewRepository.findByUserId(userId).stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    @Override
    public List<ReviewDto> getReviewsByBusinessId(Long businessId) {
        return reviewRepository.findByBusinessId(businessId).stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    @Override
    public List<ReviewDto> getReviewsByFoodId(Long foodId) {
        return reviewRepository.findByFoodId(foodId).stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public boolean deleteReview(Long reviewId, User currentUser) {
        // 1. 查找评价
        Review review = reviewRepository.findById(reviewId)
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "评价不存在"));
        
        // 2. 检查权限：只有评价的创建者或管理员可以删除
        if (!review.getUser().getId().equals(currentUser.getId()) && 
                !currentUser.getAuthorities().stream().anyMatch(a -> "ADMIN".equals(a.getName()))) {
            throw new ResponseStatusException(HttpStatus.FORBIDDEN, "无权删除此评价");
        }
        
        // 3. 执行删除（实际是标记删除）
        review.setDeleted(true);
        review.setUpdater(currentUser.getId());
        review.setUpdateTime(LocalDateTime.now());
        reviewRepository.save(review);
        
        return true;
    }

    @Override
    public Double getAverageRatingForBusiness(Long businessId) {
        // 计算平均评分
        List<Review> reviews = reviewRepository.findByBusinessId(businessId);
        if (reviews.isEmpty()) {
            return 0.0;
        }
        
        double sum = 0;
        for (Review review : reviews) {
            sum += review.getRating();
        }
        
        return sum / reviews.size();
    }
    
    /**
     * 将Review实体转换为ReviewDto
     */
    private ReviewDto convertToDto(Review review) {
        ReviewDto dto = new ReviewDto();
        dto.setId(review.getId());
        dto.setOrderId(review.getOrder().getId());
        dto.setBusinessId(review.getBusiness().getId());
        
        if (review.getFood() != null) {
            dto.setFoodId(review.getFood().getId());
            dto.setFoodName(review.getFood().getFoodName());
        }
        
        dto.setRating(review.getRating());
        dto.setContent(review.getContent());
        dto.setImages(review.getImages());
        dto.setIsAnonymous(review.getIsAnonymous());
        
        // 设置显示字段
        if (!review.getIsAnonymous()) {
            dto.setUserName(review.getUser().getUsername());
            // 用户头像可能需要另外处理
        } else {
            dto.setUserName("匿名用户");
        }
        
        dto.setOrderTime(review.getOrder().getCreateTime().format(formatter));
        dto.setReviewTime(review.getCreateTime().format(formatter));
        
        return dto;
    }
} 